#pragma once

#include <glibmm/ustring.h>
#include <vector>

#include "Exception.hpp"

namespace BuildNG
{
  Glib::ustring int_to_str(gint32 v);
  
  enum TryParseIntRes
  {
    TryParseIntRes_Success,
    TryParseIntRes_ParseError,
    TryParseIntRes_OutOfRange,
  };
  TryParseIntRes try_parse_int(const Glib::ustring &str,int &out);
  TryParseIntRes try_parse_int(const gchar *str,int &out);
  TryParseIntRes try_parse_int(const gchar *begin,const gchar *end,int &out);
  gint32 parse_int(const Glib::ustring &str);
  gint32 parse_int(const gchar *str);
  gint32 parse_int(const gchar *begin,const gchar *end);
  
  class ParseIntException : public Exception
  {
  public:
    ParseIntException(const Glib::ustring &number_str);
    ~ParseIntException() throw();
    
    virtual Glib::ustring get_message() const;
  
  private:
    Glib::ustring number_str;
  };

  std::vector<Glib::ustring> shell_parse_windows_style(const Glib::ustring &cmd_line);
  
  std::wstring    to_wstring(const Glib::ustring &in);
  Glib::ustring   to_ustring(const wchar_t *src);
  static inline Glib::ustring to_ustring(const std::wstring &src)
  {
    return to_ustring(src.c_str());
  }
  
  bool compare_string_begin(const gchar *a_begin,const gchar *a_end,const gchar *b);
  bool compare_string_segment(const gchar *a_begin,const gchar *a_end,
    const gchar *b_begin,const gchar *b_end);
  
  void copy_file(const Glib::ustring src_path,const Glib::ustring &dest_path);
  void trim(Glib::ustring &str);
  Glib::ustring get_trimmed(const Glib::ustring &in);

  int get_next_pow2_log(guint32 v);
  int get_next_pow2_log_size_t(size_t v);
  guint32 get_next_pow2(guint32 v);
  size_t get_next_pow2_size_t(size_t v);
  
  class StringSegment
  {
  public:
    const gchar *begin;
    const gchar *end;
    
    StringSegment(){}
    StringSegment(const gchar *begin,const gchar *end)
      : begin(begin),
      end(end)
    {
    }

    void trim();
  };
}
